设计模式
状态机
http://blog.csdn.net/poem_qianmo/article/details/52824776
有限状态机FSM
当你有一系列的标记成员变量,而它们只能有且仅有一个为True时,定义成枚举(enum)其实更加适合。
状态模式主要解决的就是当控制一个对象状态转换的条件表达式过于复杂的情况,它把状态的判断逻辑转移到表示不同的一系列类当中,可以把复杂的逻辑判断简单化。
步骤一、为状态定义一个接口
class HeroineState { public: virtual ~HeroineState( ) {} virtual void handleInput(Heroine& heroine, Input input) {} virtual void update(Heroine& heroine) {} };
步骤二、为每个状态定义一个类
class DuckingState : public HeroineState { public: DuckingState( ) :chargeTime_(0) { } virtual void handleInput(Heroine& heroine, Input input) { if (input == RELEASE_DOWN) { // Change to standing state... heroine.setGraphics(IMAGE_STAND); } } virtual void update(Heroine& heroine) { chargeTime_++; if (chargeTime_ > MAX_CHARGE) { heroine.superBomb( ); } } private: int chargeTime_; };
步骤三、恰当地进行状态委托
class Heroine { public: virtual void handleInput(Input input) { state_->handleInput(*this, input); } virtual void update( ) { state_->update(*this); } // Other methods... private: Heroine State* state_; };
为了“改变状态”,我们只需要将state_声明指向不同的HeroineState对象。
状态对象的存放位置:
方法一:静态状态
如果一个状态对象没有任何数据成员,那么它的惟一数据成员便是虚表指针了。那样的话,我们就没有必要创建此状态的多个实例了,因为它们的每一个实例都是相等的。
class HeroineState
{
public:
static StandingState standing;//站立状态
static DuckingState ducking;//下蹲状态
static JumpingState jumping;//跳跃状态
static DivingState diving;//下斩状态
// Other code...
};
如果我们想让主角跳跃,那么站立状态的可以这样实现:
if (input == PRESS_UP)
{
heroine.state_ = &HeroineState::jumping;
heroine.setGraphics(IMAGE_JUMP);
}
方式二:实例化状态
如果我们又动态分配了一个新的状态实例,我们需要负责清理老的状态实例。我们这里必须要相当小心,因为当前状态修改的函数是处在当前状态里面,我们需要小心地处理删除的顺序。
在handleInput方法里面可选地返回一个新的状态。当这个状态返回的时候,主角将会删除老的状态并切换到这个新的状态
void Heroine::handleInput(Input input)
{
HeroineState* state = state_->handleInput(*this, input);
if (state != NULL)
{
delete state_;
state_ = state;
}
}
站立状态可以通过创建一个新实例转换为俯卧状态:
HeroineState* StandingState::handleInput(Heroine& heroine,
Input input)
{
if (input == PRESS_DOWN)
{
// Other code...
return new DuckingState( );
}
//Stay in this state.
return NULL;
}
命令模式
定义
将一组行为抽象为对象,这个对象和其他对象一样可以被存储和传递,从而实现行为请求者与行为实现者之间的松耦合,这就是命令模式。
a